﻿using System;
using System.Diagnostics;
using System.IO;
using System.Security;
using Zo.Events;

namespace Zo.Logging
{
    /// <summary>
    /// 跟踪日志。
    /// </summary>
    public class TraceSourceLogger : LoggerBase
    {
        /// <summary>
        /// 初始化跟踪日志。
        /// </summary>
        public TraceSourceLogger(LogLevel level) : base(level)
        {
            EventManager.Instance.Register(new TraceSourceLogEventHandler());
        }

        /// <summary>
        /// 写入消息。
        /// </summary>
        /// <param name="eventType">消息类型。</param>
        /// <param name="message">消息内容。</param>
        /// <param name="args"></param>
        protected override void WriteLog(TraceEventType eventType, string message, params object[] args)
        {
            EventManager.Instance.Handle(new TraceSourceLogEvent
            {
                EventType = eventType,
                Message = GetMessage(message, args)
            });
        }
    }

    internal class TraceSourceLogEvent
    {
        public TraceEventType EventType { get; set; }

        public string Message { get; set; }
    }

    internal class TraceSourceLogEventHandler : EventHandlerBase<TraceSourceLogEvent>
    {
        /// <summary>
        /// 跟踪源。
        /// </summary>
        private readonly TraceSource _source;

        public TraceSourceLogEventHandler()
        {
            //创建一个源追踪实体。
            _source = new TraceSource("Liberty");
        }

        protected override IEventResult OnHandle(TraceSourceLogEvent envelope)
        {
            try
            {
                //指定可输出的等级
                _source.Switch.Level = SourceLevels.Critical | SourceLevels.Error | SourceLevels.Warning | SourceLevels.Information | SourceLevels.Verbose;

                //增加侦听器
                _source.Listeners.Add(new TextWriterTraceListener(GetLogFileStream(envelope.EventType)));

                //写入消息
                _source.TraceEvent(envelope.EventType, (int)envelope.EventType, envelope.Message);
                _source.Flush();
                _source.Close();

                return new EventResult { Status = true };
            }
            catch (SecurityException)
            {
                return new EventResult { Status = false };
            }
        }

        /// <summary>
        /// 流的方式打开文件
        /// </summary>
        /// <returns>文件流</returns>
        private static StreamWriter GetLogFileStream(TraceEventType eventType)
        {
            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Temp", "log", GetFolderName(eventType), DateTime.Now.ToString("yyyyMMdd"));

            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            path = Path.Combine(path, DateTime.Now.ToFileTime() + "." + (int)eventType + ".log");

            return File.AppendText(path);
        }

        /// <summary>
        /// 获得由指定类型转换成的文件夹名称。
        /// </summary>
        /// <param name="eventType">跟踪事件类型。</param>
        /// <returns>文件夹名称。</returns>
        private static string GetFolderName(TraceEventType eventType) => eventType.ToString();
    }
}